import mpi.*;
import java.net.InetAddress;  
import java.net.NetworkInterface;
import java.io.*;
import java.net.*;

/*
 * To change this template, choose Tools | Templates and open the template in
 * the editor.
 */
/**
 *
 * @author Steve
 */
public class MPIdivision {

	int my_rank; // Rank of process
	int source;  // Rank of sender
	int dest;    // Rank of receiver 
	int tag=50;  // Tag for messages (arbitrary)	
	int DIETAG = 100; //Kills all slaves
	int myrank = 0; 
	int mpi_size = 0;
	String path_to_queries = "queries/";
	String hostname = GetHostname();

	public String GetHostname()
	{
		try {    
			InetAddress addr = InetAddress.getLocalHost();
			byte [] ipAddr = addr.getAddress();
			hostname = addr.getHostName();
		}
		catch (UnknownHostException e) {
		}
		return hostname;
	}



            
	public void ProcessQueue(String[] args) throws MPIException 
	{
		MPI.Init(args);
		myrank = MPI.COMM_WORLD.Rank();
		mpi_size = MPI.COMM_WORLD.Size();
		
		if(myrank == 0) {
    			master();
		 }
      		else {
			slave();
		}
		
      		MPI.Finalize();
      	}

	public void master() throws MPIException 
	{
		long Start_time = System.currentTimeMillis();
		System.out.println("I'm master:" + hostname);
		int query_number[]  = new int[1];
		int received[] = new int[0];
		query_number[0] = 0;

		int number_files = new File(path_to_queries).list().length;
		System.out.println("Number of queries: " + number_files);

		//Send initial work queries to all servers
		for(int rank = 1; rank < mpi_size; rank++)
		{
			MPI.COMM_WORLD.Send(query_number,0,1,MPI.INT,rank,tag);
			query_number[0]++;
		}

		System.out.println("MPI size: " + mpi_size);

		//Keep looping until all files processed
		for(int i=mpi_size; i <= number_files; i++)
		{
			Status status = MPI.COMM_WORLD.Recv(received,0,1,MPI.INT,MPI.ANY_SOURCE,2);
			
			System.out.println("Received from rank: " + status.source);
			
			query_number[0] = i -1;
			MPI.COMM_WORLD.Send(query_number,0,1,MPI.INT,status.source,tag);
		}

		//receive all outstanding work from slaves
		for(int rank=1; rank < mpi_size; rank++)
		{	
			Status status = MPI.COMM_WORLD.Recv(received,0,1,MPI.INT,MPI.ANY_SOURCE,2);
			System.out.println("Received from rank: " + status.source);

		}

		long End_time = System.currentTimeMillis();
		System.out.println("********************");
		System.out.println("Took " +(End_time - Start_time)+"ms to process " + number_files + " requests");

		//Kill waiting slaves
		for(int i=1; i < mpi_size; i++)
		{
			MPI.COMM_WORLD.Send(query_number,0,1,MPI.INT,i,DIETAG);
		}


	}

	public void slave() throws MPIException
	{
        	Architect ArchitectObject = new Architect();
        	XMLDTO  QueryObject = new XMLDTO();
       	 	XMLHandler XMLobject = new XMLHandler();
	
		while(true)
		{
			int query_received[] = new int[1];

			Status status = MPI.COMM_WORLD.Recv(query_received,0,1,MPI.INT,MPI.ANY_SOURCE,MPI.ANY_TAG);
	
			if(status.tag == DIETAG)
			{
				return;
			}
			System.out.println("Slave here: " + hostname + " Rank:" + myrank +  " Received:" + query_received[0]);
	
			QueryObject = XMLobject.extract_xml(path_to_queries + "query" + query_received[0] + ".xml");
			switch (QueryObject.getCode()) 
			{
                		case 1: //Assume this case is architect activate land
                        		ArchitectObject.validateSelectedBlock(QueryObject);
	 	    			break;
                		case 2: //Assume this case is scout upload coordinate
                    			//scoutobject.validateSelectedBlock(xmlObject) // validateSelectedBlock will call subfunctions to perform each individual check *NOTE 1
                    			break;
               		 	default:    //Thorw and log exception as this case should never occur
            		}
			
			System.out.println("Rank " + myrank + "completed work");	
			//acknowledge work completed
			query_received[0] = -1;
			MPI.COMM_WORLD.Ssend(query_received,0,1,MPI.INT,0,2);
		}
	}



 

    
}
